# -*- coding: UTF-8 -*-
#-------------------------------------------------------------------------------
# Name:        serviceProvider.py
# Purpose:
#
# Author:      Drago@
#
# Created:     07.08.2009
# Copyright:   (c) Drago@ 2009
# Licence:     <your licence>
#-------------------------------------------------------------------------------
#!/usr/bin/env python

from pygs.remoting import connectServer
#from pygs.statusProvider import StatusProvider

class ServiceProvider(object):
    """
        Service provider
    """

    def __init__(self):
        object.__init__(self)
        self.serviceRegister = {}
        self.instances = {}
        self.remoteServers = {}
    
    def __del__(self):
        self.shutdown()
        
    def getServiceConfig(self, serviceName):
        assert self.serviceRegister.has_key(serviceName), "Requested service with name '%s' is not registered in ServiceProvider!" % serviceName        
        return self.serviceRegister[serviceName]
    
    def getIsRemote(self, serviceName):
        return self.getServiceConfig(serviceName).remote
            
    def createLocalInstance(self, module, className, params):
        # load class dynamycally from module
        classModule = __import__(module, fromlist=[None])
        serviceClass = getattr(classModule, className)
        serviceInstance = serviceClass()
        # set current service provider to use in class instance
        serviceInstance.setServiceProvider(self)
        return serviceInstance
    
    def createRemoteServer(self, address):
        return connectServer(address)

    def createServiceInstance(self, serviceName):        
        config = self.getServiceConfig(serviceName)
        assert not self.getIsRemote(serviceName)
        instance = self.createLocalInstance(config.module, config.className, config.params)
        return instance
    
    def getServiceParams(self, serviceName):
        assert self.serviceRegister.has_key(serviceName)
        return self.serviceRegister[serviceName].params       
    
    def startupService(self, serviceName):
        if self.instances.has_key(serviceName):
            self.instances[serviceName].startup(self.getServiceParams(serviceName))        
    
    def shutdownService(self, serviceName):
        if self.instances.has_key(serviceName):
            self.instances[serviceName].shutdown() 
            del self.instances[serviceName]
    
    def shutdown(self):
        for name in self.instances.iterkeys():
            self.shutdownService(name)
        self.remoteServers.clear()

    def getServer(self, uri):
        if not self.remoteServers.has_key(uri):
            self.remoteServers[uri] = self.createRemoteServer(uri)
        return self.remoteServers[uri]

    def remoteImplementation(self, serviceName):
        config = self.getServiceConfig(serviceName)
        return self.getServer(config.remoteAddress).implementation(serviceName)

    def implementation(self, serviceName):
        
        if self.getIsRemote(serviceName):
            return self.remoteImplementation(serviceName)
        
        if self.instances.has_key(serviceName):
            return self.instances[serviceName]
        else:
            instance = self.createServiceInstance(serviceName)
            self.instances[serviceName] = instance
            self.startupService(serviceName)
            return instance

    def registerService(self, serviceName, implementationConfig):
        assert not self.serviceRegister.has_key(serviceName)
        self.serviceRegister[serviceName] = implementationConfig
        
    def changeServiceConfig(self, serviceName, implementationConfig):
        if not self.serviceRegister.has_key(serviceName):
            self.registerService(serviceName, implementationConfig)
        else:
            oldConfig = self.getServiceConfig(serviceName)
            if not implementationConfig.isEqual(oldConfig):
                self.shutdownService(serviceName)
                self.serviceRegister[serviceName] = implementationConfig
                
    def setConfig(self, config):
        config.registerServices(self)
        
    def setConfigData(self, configData):
        from pygs.serviceProviderConfig import ServiceProviderConfig
        config = ServiceProviderConfig(configData)
        self.setConfig(config)
        
from pygs.serviceProviderConfig import defaultServiceProviderConfig

serviceProviderInstance = ServiceProvider()
serviceProviderInstance.setConfig(defaultServiceProviderConfig)